/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package com.cognition.util.j2me;

import java.util.Vector;

/**
 * Utility class for working with data types.
 * @author Richard Schilling
 */
public final class DataTypeUtil {

    /**
     * Returns the specified boolean array as a byte array, where each element
     * of the resulting array has the value of 0 (false), or 1 (true).
     * @param b the boolean array to convert
     * @return a byte array of either 0 (false) or 1 (true).
     */
    public static byte[] toByteArray(boolean[] b) {
        if (b == null) {
            throw new IllegalArgumentException("boolean array cannot be null.");
        }
        byte[] result = new byte[b.length];
        for (int i = 0; i < result.length; i++) {
            result[i] = (byte) (b[i] ? 1 : 0);
        }
        return result;
    }



    public static float toFloat(byte[] b) {
            int bits = 0;
            int i = 0;
            for (int shifter = 3; shifter >= 0; shifter--) {
                bits |= ((int) b[i] & 0xff) << (shifter * 8);
                i++;
        }

            return Float.intBitsToFloat(bits);
    }

    public static byte[] toByteArray(float f) {
        int i = Float.floatToIntBits(f);
        return toByteArray(i);
    }

    public static byte[] toByteArray(boolean b){
        byte[] result = new byte[1];
        result[0] = (byte) (b ? 1 : 0);
        return result;
    }

    public static boolean[] toBooleanArray(byte[] b) {
        if (b == null) {
            throw new IllegalArgumentException("byte array cannot be null.");
        }
        boolean[] result = new boolean[b.length];
        for (int i = 0; i < result.length; i++) {
            result[i] = (b[i] == 1 ? true : false);
        }
        return result;
    }

    public static byte[] toByteArray(long data) {
        return new byte[]{
                    (byte) ((data >> 56) & 0xff),
                    (byte) ((data >> 48) & 0xff),
                    (byte) ((data >> 40) & 0xff),
                    (byte) ((data >> 32) & 0xff),
                    (byte) ((data >> 24) & 0xff),
                    (byte) ((data >> 16) & 0xff),
                    (byte) ((data >> 8) & 0xff),
                    (byte) ((data >> 0) & 0xff),};
    }

    /**
     * Utility method to convert the specified integer <code>value</code> into a byte array.
     * Most significant byte is returned in position 0 of the array.
     * @param value the value to convert into a byte array
     * @return a byte array that contains the bytes representation of the passed value.
     */
    public static byte[] toByteArray(int data) {
        return new byte[]{
                (byte) ((data >> 24) & 0xff),
                (byte) ((data >> 16) & 0xff),
                (byte) ((data >> 8) & 0xff),
                (byte) ((data >> 0) & 0xff),};
    }

    public static long toLong(byte[] data) {
        if (data == null || data.length != 8) {
            return 0x0;
        }
        // ----------
        return (long) ( // (Below) convert to longs before shift because digits
                // are lost with ints beyond the 32-bit limit
                (long) (0xff & data[0]) << 56 |
                (long) (0xff & data[1]) << 48 |
                (long) (0xff & data[2]) << 40 |
                (long) (0xff & data[3]) << 32 |
                (long) (0xff & data[4]) << 24 |
                (long) (0xff & data[5]) << 16 |
                (long) (0xff & data[6]) << 8 |
                (long) (0xff & data[7]) << 0);
    }

    public static int toInt(byte[] data){
        if (data == null || data.length != 4){
                return 0x0;
        }

        return (int)(
                (int) (0xff & data[0]) << 24 |
                (int) (0xff & data[1]) << 16 |
                (int) (0xff & data[2]) << 8 |
                (int) (0xff & data[3]) << 0);

    }

    /**
     * Utility method to convert an unsigned byte to an integer.  Note that in Java,
     * bytes are normally signed in the range of -127 to 127.  Special processing is needed
     * to convert the byte value to it's equivalent unsigned byte value.
     *
     * @param b the unsigned byte to convert.
     * @return the value of b as an unsigned byte (0 to 254).
     */
    public static int unsignedByteToInt(byte b) {
        return (int) b & 0xFF;
    }

    public static String urlEncode(String sUrl) {
        // :/?#[]@!$&'()*+,;=
        int i = 0;


        StringBuffer result = new StringBuffer();

        /*
         *
         * The official table:

                ;       %3B
                ?       %3F
                /       %2F
                :       %3A
                #       %23
                &       %24
                =       %3D
                +       %2B
                $       %26
                ,       %2C
                <space>         %20 or +
                %       %25
                <       %3C
                >       %3E
                ~       %7E
                %       %25

        */

        while (i < sUrl.length()) {
            if (sUrl.charAt(i) == '<') {
                result.append("%3C");
            } else if (sUrl.charAt(i) == '>') {
                result.append("%3E");
            } else if (sUrl.charAt(i) == ' ') {
                result.append("%20");
            } else if (sUrl.charAt(i) == '-') {
                result.append("%2D");
            } else if (sUrl.charAt(i) == ':') {
                result.append("%3A");
            } else if (sUrl.charAt(i) == '/') {
                result.append("%2F");
            } else if (sUrl.charAt(i) == '?') {
                result.append("%3F");
            } else if (sUrl.charAt(i) == '#') {
                result.append("%23");
            } else if (sUrl.charAt(i) == '[') {
                result.append("%5B");
            } else if (sUrl.charAt(i) == ']') {
                result.append("%5D");
            } else if (sUrl.charAt(i) == '@') {
                result.append("%40");
            } else if (sUrl.charAt(i) == '!') {
                result.append("%21");
            } else if (sUrl.charAt(i) == '$') {
                result.append("%24");
            } else if (sUrl.charAt(i) == '&') {
                result.append("%26");
            } else if (sUrl.charAt(i) == '\'') {
                result.append("%27");
            } else if (sUrl.charAt(i) == '(') {
                result.append("%28");
            } else if (sUrl.charAt(i) == ')') {
                result.append("%29");
            } else if (sUrl.charAt(i) == '*') {
                result.append("%2A");
            } else if (sUrl.charAt(i) == '+') {
                result.append("%2B");
            } else if (sUrl.charAt(i) == ',') {
                result.append("%2C");
            } else if (sUrl.charAt(i) == ';') {
                result.append("%3B");
            } else if (sUrl.charAt(i) == '=') {
                result.append("%3D");
            } else {
                result.append(sUrl.charAt(i));
            }
            i++;
        }
        return result.toString();
    }


    public static String[] split(String inString, String delimeter) {
        String[] retAr;
          try {
            Vector vec = new Vector();
               int indexA = 0;
                  int indexB = inString.indexOf(delimeter);

               while (indexB != -1) {
                   vec.addElement(new String(inString.substring(indexA, indexB)));
                          indexA = indexB + delimeter.length();
                    indexB = inString.indexOf(delimeter, indexA);
            }
                vec.addElement(new String(inString.substring(indexA, inString
                            .length())));
            retAr = new String[vec.size()];
                  for (int i = 0; i < vec.size(); i++) {
                   retAr[i] = vec.elementAt(i).toString();
                  }
        } catch (Exception e) {
                  String[] ar = { e.toString() };
                  return ar;
       }
        return retAr;
  }


    public static final String[] CR_LF = {"\n", "\r"};
    /**
     * Strips a set of characters from the end of a string.
     * @param s1 The string to strip.
     * @param stripValues The strings to strip off the end of s1.
     * @return a new string reference that is s1 with all the values found in stripValues stripped off the end.
     */
    public static String stripEnd(String s1, String[] stripValues){
        String result = new String(s1);

        int endString = endsWithString(s1, stripValues);
        while (endString > -1){

                int endPos = DataTypeUtil.lastIndexOf(result, stripValues[endString]);
                result = result.substring(0, endPos);
                endString = endsWithString(result, stripValues);

        }
        return result;

    }

    /**
     * Returns the index of the string in endingValues that s1 ends with.
     * @param s1 the string to test.
     * @param endingValues an array of values to test to look for at the end of s1.
     * @return the index in endingValues that is found at the end of s1.
     */
    public static int endsWithString(String s1, String[] endingValues){


        for (int i = 0; i < endingValues.length; i++){
                if (s1.endsWith(endingValues[i]))
                        return i;
        }
        return -1;
    }

    /**
     * Returns the last index of s2 within s1 or -1 if s2 is not found in s1.
     * @param s1 the string to search
     * @param s2 the string to search for in s1.
     * @return the position of the last place in s1 that s2 can be found or -1 if s2 is not in s1.
     */
    public static int lastIndexOf(String s1, String s2){


        int result = s1.length()-1;


        while (result > -1){

                if (s1.startsWith(s2, result))
                        return result;

                result--;
        }

        return result;
    }

    public static boolean equals(byte[] b1, byte[] b2){

        if (b1 == null && b2 == null)
            return true;

        if (b1 == null && b2 != null)
            return false;

        if (b1 != null && b2 == null)
            return false;

        if (b1.length != b2.length)
            return false;

        for (int i = 0; i < b1.length; i++){
            if (b1[i] != b2[i])
                return false;
        }

        return true;
    }

    /**
     * Clones a string array.  Each member is also cloned.
     * Some phones can't clone String[].
     * @param sArray the array to clone
     * @return an array with cloned contents.
     */
    public static String[] clone(String[] sArray){

        if (sArray == null || sArray.length == 0)
            return new String[0];


        String[] result = new String[sArray.length];
        for (int i = 0; i < sArray.length; i++){
            result[i] = new String(sArray[i]);
        }

        return result;
    }



}
